package org.jeecg.modules.wmhb.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.constant.UserConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.vo.SelectTreeModel;
import org.jeecg.modules.wmhb.dto.req.ProductBomReqDto;
import org.jeecg.modules.wmhb.entity.WmContractProduct;
import org.jeecg.modules.wmhb.entity.WmPlan;
import org.jeecg.modules.wmhb.entity.WmPlanLog;
import org.jeecg.modules.wmhb.entity.WmTask;
import org.jeecg.modules.wmhb.mapper.WmContractProductMapper;
import org.jeecg.modules.wmhb.mapper.WmPlanLogMapper;
import org.jeecg.modules.wmhb.mapper.WmPlanMapper;
import org.jeecg.modules.wmhb.mapper.WmTaskMapper;
import org.jeecg.modules.wmhb.service.IWmPlanService;
import org.jeecg.modules.wmhb.dto.res.ProductBomResDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * @Description: 项目计划
 * @Author: jeecg-boot
 * @Date:   2025-09-28
 * @Version: V1.0
 */
@Service
public class WmPlanServiceImpl extends ServiceImpl<WmPlanMapper, WmPlan> implements IWmPlanService {

    @Autowired
    private WmContractProductMapper contractProductMapper;
    @Autowired
    private WmPlanLogMapper planLogMapper;
    @Autowired
    private WmTaskMapper taskMapper;

	@Override
	public void addWmPlan(WmPlan wmPlan) {
	    //新增时设置hasChild为0
	    wmPlan.setHasChild(IWmPlanService.NOCHILD);
		if(oConvertUtils.isEmpty(wmPlan.getPid())){
			wmPlan.setPid(IWmPlanService.ROOT_PID_VALUE);
            wmPlan.setAncestors(IWmPlanService.ANCESTORS);
		}else{
			//如果当前节点父ID不为空 则设置父节点的hasChildren 为1
			WmPlan parent = baseMapper.selectById(wmPlan.getPid());
			if(parent!=null && !"1".equals(parent.getHasChild())){
				parent.setHasChild("1");
				baseMapper.updateById(parent);
			}

            if(parent != null) {
                wmPlan.setAncestors(parent.getAncestors() + "," + parent.getId());
            }
		}
		baseMapper.insert(wmPlan);
	}
	
	@Override
	public void updateWmPlan(WmPlan wmPlan) {
		WmPlan entity = this.getById(wmPlan.getId());
		if(entity==null) {
			throw new JeecgBootException("未找到对应实体");
		}
		String old_pid = entity.getPid();
		String new_pid = wmPlan.getPid();
		if(!old_pid.equals(new_pid)) {
			updateOldParentNode(old_pid);
			if(oConvertUtils.isEmpty(new_pid)){
				wmPlan.setPid(IWmPlanService.ROOT_PID_VALUE);
			}
			if(!IWmPlanService.ROOT_PID_VALUE.equals(wmPlan.getPid())) {
				baseMapper.updateTreeNodeStatus(wmPlan.getPid(), IWmPlanService.HASCHILD);
			}
		}
		baseMapper.updateById(wmPlan);
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteWmPlan(String id) throws JeecgBootException {
		//查询选中节点下所有子节点一并删除
        id = this.queryTreeChildIds(id);
        if(id.indexOf(",")>0) {
            StringBuffer sb = new StringBuffer();
            String[] idArr = id.split(",");
            for (String idVal : idArr) {
                if(idVal != null){
                    WmPlan wmPlan = this.getById(idVal);
                    String pidVal = wmPlan.getPid();
                    //查询此节点上一级是否还有其他子节点
                    List<WmPlan> dataList = baseMapper.selectList(new QueryWrapper<WmPlan>().eq("pid", pidVal).notIn("id",Arrays.asList(idArr)));
                    boolean flag = (dataList == null || dataList.size() == 0) && !Arrays.asList(idArr).contains(pidVal) && !sb.toString().contains(pidVal);
                    if(flag){
                        //如果当前节点原本有子节点 现在木有了，更新状态
                        sb.append(pidVal).append(",");
                    }
                }
            }
            //批量删除节点
            baseMapper.deleteBatchIds(Arrays.asList(idArr));
            //修改已无子节点的标识
            String[] pidArr = sb.toString().split(",");
            for(String pid : pidArr){
                this.updateOldParentNode(pid);
            }
        }else{
            WmPlan wmPlan = this.getById(id);
            if(wmPlan==null) {
                throw new JeecgBootException("未找到对应实体");
            }
            updateOldParentNode(wmPlan.getPid());
            baseMapper.deleteById(id);
        }
	}
	
	@Override
    public List<WmPlan> queryTreeListNoPage(QueryWrapper<WmPlan> queryWrapper) {
        List<WmPlan> dataList = baseMapper.selectList(queryWrapper);
        List<WmPlan> mapList = new ArrayList<>();
        for(WmPlan data : dataList){
            String pidVal = data.getPid();
            //递归查询子节点的根节点
            if(pidVal != null && !IWmPlanService.NOCHILD.equals(pidVal)){
                WmPlan rootVal = this.getTreeRoot(pidVal);
                if(rootVal != null && !mapList.contains(rootVal)){
                    mapList.add(rootVal);
                }
            }else{
                if(!mapList.contains(data)){
                    mapList.add(data);
                }
            }
        }
        return mapList;
    }

    @Override
    public List<SelectTreeModel> queryListByCode(String parentCode) {
        String pid = ROOT_PID_VALUE;
        if (oConvertUtils.isNotEmpty(parentCode)) {
            LambdaQueryWrapper<WmPlan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WmPlan::getPid, parentCode);
            List<WmPlan> list = baseMapper.selectList(queryWrapper);
            if (list == null || list.size() == 0) {
                throw new JeecgBootException("该编码【" + parentCode + "】不存在，请核实!");
            }
            if (list.size() > 1) {
                throw new JeecgBootException("该编码【" + parentCode + "】存在多个，请核实!");
            }
            pid = list.get(0).getId();
        }
        return baseMapper.queryListByPid(pid, null);
    }

    @Override
    public List<SelectTreeModel> queryListByPid(String pid) {
        if (oConvertUtils.isEmpty(pid)) {
            pid = ROOT_PID_VALUE;
        }
        return baseMapper.queryListByPid(pid, null);
    }

	/**
	 * 根据所传pid查询旧的父级节点的子节点并修改相应状态值
	 * @param pid
	 */
	private void updateOldParentNode(String pid) {
		if(!IWmPlanService.ROOT_PID_VALUE.equals(pid)) {
			Long count = baseMapper.selectCount(new QueryWrapper<WmPlan>().eq("pid", pid));
			if(count==null || count<=1) {
				baseMapper.updateTreeNodeStatus(pid, IWmPlanService.NOCHILD);
			}
		}
	}

	/**
     * 递归查询节点的根节点
     * @param pidVal
     * @return
     */
    private WmPlan getTreeRoot(String pidVal){
        WmPlan data =  baseMapper.selectById(pidVal);
        if(data != null && !IWmPlanService.ROOT_PID_VALUE.equals(data.getPid())){
            return this.getTreeRoot(data.getPid());
        }else{
            return data;
        }
    }

    /**
     * 根据id查询所有子节点id
     * @param ids
     * @return
     */
    private String queryTreeChildIds(String ids) {
        //获取id数组
        String[] idArr = ids.split(",");
        StringBuffer sb = new StringBuffer();
        for (String pidVal : idArr) {
            if(pidVal != null){
                if(!sb.toString().contains(pidVal)){
                    if(sb.toString().length() > 0){
                        sb.append(",");
                    }
                    sb.append(pidVal);
                    this.getTreeChildIds(pidVal,sb);
                }
            }
        }
        return sb.toString();
    }

    /**
     * 递归查询所有子节点
     * @param pidVal
     * @param sb
     * @return
     */
    private StringBuffer getTreeChildIds(String pidVal,StringBuffer sb){
        List<WmPlan> dataList = baseMapper.selectList(new QueryWrapper<WmPlan>().eq("pid", pidVal));
        if(dataList != null && dataList.size()>0){
            for(WmPlan tree : dataList) {
                if(!sb.toString().contains(tree.getId())){
                    sb.append(",").append(tree.getId());
                }
                this.getTreeChildIds(tree.getId(),sb);
            }
        }
        return sb;
    }

    @Override
    @Transactional
    public void addWmPlanBatch(List<String> contractProductIdList){
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        for(String contractProductId: contractProductIdList){
            WmContractProduct wmContractProduct = contractProductMapper.selectById(contractProductId);
            WmPlan wmPlanExist = baseMapper.findByContractProduct(contractProductId);//是否已经生成过计划
            if(wmContractProduct != null && wmPlanExist == null){
                WmPlan wmPlan = new WmPlan();
                wmPlan.setName(wmContractProduct.getName());
                wmPlan.setContractProductId(wmContractProduct.getId());
                wmPlan.setCurrentUserId(sysUser.getId());
                wmPlan.setPid(UserConstant.ZERO);
                wmPlan.setHasChild(UserConstant.SYS_NO);
                wmPlan.setPlanStatus(UserConstant.PLAN_STATUS_PREPARE);
                wmPlan.setPlanUserId(sysUser.getId());
                baseMapper.insert(wmPlan);

                WmPlanLog wmPlanLog = new WmPlanLog();
                wmPlanLog.setWmPlanId(wmPlan.getId());
                wmPlanLog.setUserId(sysUser.getId());
                wmPlanLog.setMemo("创建计划");
                planLogMapper.insert(wmPlanLog);
            }
        }
    };

    @Override
    @Transactional
    public void assignPlan(List<String> idList, String deptId, String userId){
        for(String planId: idList){
            WmPlan wmPlan = baseMapper.selectById(planId);
            if(wmPlan != null){
                wmPlan.setBuId(deptId);
                if(StringUtils.isEmpty(userId)){
                    WmPlanLog wmPlanLog = new WmPlanLog();
                    wmPlan.setCurrentUserId(userId);
                    wmPlanLog.setUserId(userId);
                    wmPlanLog.setWmPlanId(planId);
                    wmPlanLog.setMemo("计划分配");
                    planLogMapper.insert(wmPlanLog);
                }
                baseMapper.updateById(wmPlan);
            }
        }
    };

    @Override
    @Transactional
    public void transferPlan(List<String> idList, String userId, String memo){
        for(String planId: idList){
            WmPlan wmPlan = baseMapper.selectById(planId);
            if(wmPlan != null){
                WmPlanLog wmPlanLog = new WmPlanLog();
                wmPlan.setCurrentUserId(userId);
                baseMapper.updateById(wmPlan);

                wmPlanLog.setWmPlanId(planId);
                wmPlanLog.setUserId(userId);
                if(StringUtils.isEmpty(memo)) {
                    wmPlanLog.setMemo(memo);
                }
                else{
                    wmPlanLog.setMemo("计划转办");
                }
                planLogMapper.insert(wmPlanLog);
            }
        }
    };

    @Override
    public ProductBomResDto uploadProductBom(List<ProductBomReqDto> list, String wmPlanId){
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        WmPlan wmPlanExist = baseMapper.selectById(wmPlanId);
        if(wmPlanExist == null){
            throw new RuntimeException("产品不存在");
        }
        List<ProductBomReqDto> newList = new ArrayList<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String batchNo = format.format(new Date());
        try {
            //循环处理上传的产品
            for (ProductBomReqDto bomNode : list) {
                if (StringUtils.isEmpty(bomNode.getName())) {
                    bomNode.setStatus("物料名称缺失");
                    bomNode.setResult("fail");
                    newList.add(bomNode);
                    continue;
                }

                //新增子计划信息
                WmPlan wmPlan = new WmPlan();
                wmPlan.setContractProductId(wmPlanExist.getContractProductId());
                wmPlan.setName(bomNode.getName());
                wmPlan.setDesignUserId(sysUser.getId());
                if(!StringUtils.isEmpty(bomNode.getPcode())) {
                    WmPlan wmPlanParent = findByCodeAndContractProduct(bomNode.getPcode(), wmPlanExist.getContractProductId());
                    if (wmPlanParent != null) {
                        wmPlan.setPid(wmPlanParent.getId());
                        wmPlan.setBuId(wmPlanParent.getBuId());
                        wmPlan.setCurrentUserId(wmPlanParent.getCurrentUserId());
                    }
                }
                addWmPlan(wmPlan);

                bomNode.setStatus("导入成功");
                bomNode.setResult("success");
                newList.add(bomNode);
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        ProductBomResDto wmBomResultVo = new ProductBomResDto();
        wmBomResultVo.setBomNodeList(newList);
        wmBomResultVo.setBatchNo(batchNo);
        return wmBomResultVo;
    };

    //通过编码和合同产品ID查询计划
    private WmPlan findByCodeAndContractProduct(String code, String contractProductId){
        LambdaQueryWrapper<WmPlan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmPlan::getCode, code).eq(WmPlan::getContractProductId, contractProductId).last("LIMIT 1");
        WmPlan wmPlanParent = getOne(queryWrapper);
        return wmPlanParent;
    };

    @Override
    public void generateDesign(List<String> idList, String userId){
        for(String planId: idList){
            WmPlan wmPlan = baseMapper.selectById(planId);
            if(wmPlan != null){
                wmPlan.setCurrentUserId(userId);
                wmPlan.setDesignUserId(userId);
                wmPlan.setDesignStatus(UserConstant.DESIGN_STATUS_PREPARE);
                baseMapper.updateById(wmPlan);

                WmPlanLog wmPlanLog = new WmPlanLog();
                wmPlanLog.setWmPlanId(planId);
                wmPlanLog.setUserId(userId);
                wmPlanLog.setMemo("生成技术任务");
                planLogMapper.insert(wmPlanLog);
            }
        }
    };

    @Override
    @Transactional
    public void generateProcess(List<String> idList, String userId){
        for(String planId: idList){
            WmPlan wmPlan = baseMapper.selectById(planId);
            if(wmPlan != null && wmPlan.getHasChild().equals(UserConstant.ZERO)){
                wmPlan.setCurrentUserId(userId);
                wmPlan.setProduceUserId(userId);
                wmPlan.setProcessStatus(UserConstant.PROCESS_STATUS_PREPARE);
                baseMapper.updateById(wmPlan);

                //生成任务
                WmTask wmTask = new WmTask();
                wmTask.setPlanId(planId);
                wmTask.setName(wmPlan.getName());
                wmTask.setPid(UserConstant.ZERO);
                wmTask.setHasChild(UserConstant.ZERO);
                wmTask.setAncestors(UserConstant.ZERO);
                wmTask.setQuantity(wmPlan.getQuantity());
                taskMapper.insert(wmTask);

                //日志
                WmPlanLog wmPlanLog = new WmPlanLog();
                wmPlanLog.setWmPlanId(planId);
                wmPlanLog.setUserId(userId);
                wmPlanLog.setMemo("生成工艺任务");
                planLogMapper.insert(wmPlanLog);
            }
        }
    };

    @Override
    @Transactional
    public void confirmProcess(String id, String type, String processAuditUserId){
        WmPlan wmPlan = baseMapper.selectById(id);
        if(!wmPlan.getProcessStatus().equals(UserConstant.PROCESS_STATUS_PREPARE)){{
            throw new RuntimeException("只有草稿状态能确认");
        }}

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        wmPlan.setProcessStatus(UserConstant.PROCESS_STATUS_CONFIRMED); //更新工艺状态
        wmPlan.setProcessUserId(sysUser.getId());
        wmPlan.setProcessAuditUserId(processAuditUserId);//设置工艺审核人员
        wmPlan.setCurrentUserId(processAuditUserId);
        baseMapper.updateById(wmPlan);
        taskMapper.confirmProcess(id, type, sysUser.getId(), UserConstant.PROCESS_STATUS_CONFIRMED);//更改任务类型和设置工艺人员

        WmPlanLog wmPlanLog = new WmPlanLog();
        wmPlanLog.setWmPlanId(id);
        wmPlanLog.setUserId(sysUser.getId());
        wmPlanLog.setMemo("确认工艺任务");
        planLogMapper.insert(wmPlanLog);
    };

    @Override
    @Transactional
    public void auditProcess(String id, String processStatus, String remark){
        WmPlan wmPlan = baseMapper.selectById(id);
        if(!wmPlan.getProcessStatus().equals(UserConstant.PROCESS_STATUS_CONFIRMED)){{
            throw new RuntimeException("只有确认状态能审核");
        }}

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if(processStatus.equals(UserConstant.AUDIT_AGREE)){
            wmPlan.setProcessStatus(UserConstant.PROCESS_STATUS_FINISHED); //更新工艺状态
            wmPlan.setCurrentUserId(sysUser.getId());
        }
        else{
            wmPlan.setProcessAuditUserId("");
            wmPlan.setProcessStatus(UserConstant.PROCESS_STATUS_PREPARE);
            wmPlan.setCurrentUserId(wmPlan.getProcessUserId());//当前用户返回工艺人员
        }
        baseMapper.updateById(wmPlan);
        taskMapper.auditProcess(id, wmPlan.getProcessAuditUserId(), UserConstant.PROCESS_STATUS_FINISHED);

        WmPlanLog wmPlanLog = new WmPlanLog();
        wmPlanLog.setWmPlanId(id);
        wmPlanLog.setUserId(sysUser.getId());
        wmPlanLog.setMemo("审核工艺任务");
        planLogMapper.insert(wmPlanLog);
    };
}
